package iteso.compiladores.logo;

import iteso.compiladores.logo.lexer.LexerException;
import iteso.compiladores.logo.node.*;
import iteso.compiladores.logo.analysis.*;
import iteso.compiladores.logo.lexer.Lexer;
import iteso.compiladores.logo.parser.Parser;
import iteso.compiladores.logo.parser.ParserException;
import java.awt.Color;
import java.awt.Graphics;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.lang.Math.*;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author armandomolina
 */
public class Translator extends DepthFirstAdapter {



    
    @Override
public void caseAForward1Mforward(AForward1Mforward node) {
        inAForward1Mforward(node);
        if (node.getForward() != null && node.getInteger() != null) {
            TInteger integ = node.getInteger();
            int dist = Integer.parseInt(integ.getText());
            System.out.println("Dibujando una linea de " + dist);
            Helper.add(Math.abs(dist));
            if (dist<0)Helper.setAngleMegaman(180);
        }
        outAForward1Mforward(node);
    }


    @Override
public void caseAForward2Mforward(AForward2Mforward node) {
        inAForward2Mforward(node);
        if(node.getForward() != null && node.getIdentifier() != null) {
            TIdentifier identifier = node.getIdentifier();
            String temp = Helper.variables.get(identifier.getText()).toString();
            double dist = Double.parseDouble(temp);
            Helper.add(Math.abs((int)dist));
            System.out.println("Dibujando una linea de " + Helper.variables.get(identifier.getText()));
        }
        outAForward2Mforward(node);
    }

    @Override
public void caseALeftMleft(ALeftMleft node) {
        inALeftMleft(node);
        if (node.getLeft() != null && node.getInteger() != null) {
            TInteger integ = node.getInteger();
            Integer degree = 0;
            degree = Integer.parseInt(integ.getText());
            Helper.setAngleMegaman(-degree);
            System.out.println("Dando vuelta a la izquierda " + integ + " grados");
        }
        outALeftMleft(node);

    }

    @Override
public void caseARightMright(ARightMright node) {
        inARightMright(node);
        if (node.getRight() != null && node.getInteger() != null) {
            TInteger integ = node.getInteger();
            Integer degree = 0;
            degree = Integer.parseInt(integ.getText());
            Helper.setAngleMegaman(degree);
            System.out.println("Dando vuelta a la derecha " + integ + " grados");
        }
        outARightMright(node);

    }

    @Override
public void caseABack1Mback(ABack1Mback node) {
        inABack1Mback(node);
        if(node.getBack() != null && node.getInteger() != null)
        {
            TInteger integ = node.getInteger();
            int dist = Integer.parseInt(integ.getText());
            Helper.setAngleMegaman(180);
            if (dist<0)Helper.setAngleMegaman(180);
            Helper.add(Math.abs(dist));
            if (dist<0)Helper.setAngleMegaman(180);
        	Helper.setAngleMegaman(180);
            System.out.println("Regresando  " + integ);
        }
        outABack1Mback(node);
    }

    @Override
public void caseABack2Mback(ABack2Mback node) {
        inABack2Mback(node);
        if(node.getBack() != null && node.getIdentifier() != null) {
            TIdentifier identifier = node.getIdentifier();
            String temp = Helper.variables.get(identifier.getText()).toString();
            double dist = Double.parseDouble(temp);
            Helper.setAngleMegaman(180);
            if (dist<0)Helper.setAngleMegaman(180);
            Helper.add(Math.abs((int)dist));
            if (dist<0)Helper.setAngleMegaman(180);
        	Helper.setAngleMegaman(180);
            System.out.println("Regresando  " + identifier);
            
        }
        outABack2Mback(node);
    }

    @Override
public void caseARepeat1Mrepeat(ARepeat1Mrepeat node) {
        inARepeat1Mrepeat(node);
        TInteger integ = null;
        PInstructionlist stmt = null;
        if (node.getInteger() != null) {
            integ = node.getInteger();
        }

        if (node.getInstructionlist() != null) {
            stmt = node.getInstructionlist();
        }

        //Implementamos ciclo
        int repeat = Integer.parseInt(integ.getText());
        for (int i = 0; i < repeat; i++) {
            stmt.apply(this);
        }
        outARepeat1Mrepeat(node);
    }

@Override
public void caseAAddMadd(AAddMadd node)
    {
        inAAddMadd(node);
        if(node.getSum() != null && node.getRight() != null && node.getLeft() != null)
        {
                TDouble leftInteg = node.getLeft();
                TDouble rightInteg = node.getRight();
                Double d = Double.parseDouble(leftInteg.getText()) + Double.parseDouble(rightInteg.getText());
                System.out.println("Sumando " + leftInteg + " + " + rightInteg);


                //double result = (Double.parseDouble(leftInteg);


                System.out.println("Resultado = " + d);

        }
        outAAddMadd(node);
    }

    @Override
public void caseADifferenceMdif(ADifferenceMdif node)
    {
        inADifferenceMdif(node);
        if(node.getDifference() != null && node.getR() != null && node.getL() != null)
        {
                TDouble leftInteg = node.getL();
                TDouble rightInteg = node.getR();
                System.out.println("Diferencia de " + leftInteg + " - " + rightInteg);
                double result = Double.parseDouble(leftInteg.getText()) - Double.parseDouble(rightInteg.getText());
                System.out.println("Result = " + result);
        }
        outADifferenceMdif(node);
    }

    @Override
 public void caseARoundMround(ARoundMround node)
    {
        inARoundMround(node);
        if(node.getRound() != null && node.getDouble() != null)
        {
           TDouble num = node.getDouble();
           double temp = Double.parseDouble(num.getText());
           Math miMath = null;
           float temp2 = Double.valueOf(temp).floatValue();
           int result = Math.round(temp2);
           System.out.println("Redondeo de " + num + " es " + result);
        }
        outARoundMround(node);
    }

    @Override
 public void caseAMprod(AMprod node)
    {
        inAMprod(node);
        if(node.getMultiplica() != null && node.getR() != null && node.getL() != null)
        {
            TDouble leftInteg = node.getL();
                TDouble rightInteg = node.getR();
                System.out.println("Multiplicando " + leftInteg + " * " + rightInteg);
                Double d = Double.parseDouble(leftInteg.getText()) * Double.parseDouble(rightInteg.getText());
                System.out.println("Result = " + d);  
        }
        outAMprod(node);
    }

    @Override
 public void caseAModuloMmodulo(AModuloMmodulo node)
    {
        inAModuloMmodulo(node);
        if(node.getModulo() != null && node.getR() != null && node.getL() != null)
        {
            TDouble leftInteg = node.getL();
                TDouble rightInteg = node.getR();
                System.out.println("Modulo " + leftInteg + " y " + rightInteg);
                Double d = Double.parseDouble(leftInteg.getText()) / Double.parseDouble(rightInteg.getText());
                System.out.println("Result = " + d);  
        }
        outAModuloMmodulo(node);
    }

    @Override
public void caseASqrtMsqrt(ASqrtMsqrt node)
    {
        inASqrtMsqrt(node);
        if(node.getSqrt() != null || node.getInteger() != null){
                TInteger integer = node.getInteger();
                System.out.println("Raiz cuadrada de " + integer);
                int result = (int)Math.sqrt(Double.parseDouble(integer.getText()));
                System.out.println("Resultado = " + result); 
        }
        outASqrtMsqrt(node);
    }

    @Override
public void caseAMpower(AMpower node)
    {
        inAMpower(node);
        if(node.getPower() != null && node.getL() != null && node.getR() != null)
        {
                TDouble leftInteg = node.getL();
                TDouble rightInteg = node.getR();
                System.out.println("Elevando " + leftInteg + " a la " + rightInteg);
                int result = (int)Math.pow(Double.parseDouble(leftInteg.getText()), Double.parseDouble(rightInteg.getText()));
                System.out.println("Result = " + result); 
        }
        outAMpower(node);
    }

    @Override
public void caseAMexp(AMexp node)
    {
        inAMexp(node);
        if(node.getExp() != null || node.getInteger() != null){
                TInteger integer = node.getInteger();
                System.out.println(" " + integer);
                double result = Math.exp(Double.parseDouble(integer.getText()));
                System.out.println("Resultado = " + result);
        }
        outAMexp(node);
    }

    @Override
public void caseAGtMgt(AGtMgt node){
    inAGtMgt(node);
    if(node.getGreaterthan() != null && node.getL() != null && node.getR() != null)
    {
        TDouble doubleLeft = node.getL();
        TDouble doubleRight = node.getR();
        System.out.println(doubleLeft +" Greater than " + doubleRight);
        
        
    }
    outAGtMgt(node);
}

    @Override
public void caseALtMlt(ALtMlt node){
    inALtMlt(node);
    if(node.getLowerthan() != null && node.getL() != null && node.getR() != null)
    {
        TDouble doubleLeft = node.getL();
        TDouble doubleRight = node.getR();
        System.out.println(doubleLeft +" Lower than " + doubleRight);
        
    }
    outALtMlt(node);
}

    @Override
public void caseAMakeMmake(AMakeMmake node){
    inAMakeMmake(node);
    if(node.getMake() != null && node.getIdentifier() !=null && node.getDouble() != null){
        TIdentifier identifier = node.getIdentifier();
        
        Helper.variables.put(identifier.getText(), node.getDouble());
        
        System.out.println("Make  " + Helper.variables.get(identifier.getText()));
    }
}

    @Override
public void caseAMstop(AMstop node){
    inAMstop(node);
    if(node.getStop() != null){
        System.out.println("Stop");
    }
}

    @Override
public void caseAGotoMgoto(AGotoMgoto node){
    inAGotoMgoto(node);
    if(node.getGoto() != null && node.getIdentifier() != null){
        //System.out.println(proc.containsKey(node.getIdentifier().getText()));
        String key = String.valueOf(Helper.procedimientos.get(node.getIdentifier().getText()));
        //System.out.println("GoTo " + key);       
                
        Parser p =
			new Parser(
			new Lexer(
			new PushbackReader(
                        new StringReader(key) {

                @Override
                public int read(char[] cbuf, int off, int len) throws IOException {
                    throw new UnsupportedOperationException("Not supported yet.");
                }
            }
            ) 
                        
            ));
            try {
                Start tree = p.parse();
                tree.apply(new Translator());
            } catch (ParserException ex) {
                Logger.getLogger(Translator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (LexerException ex) {
                Logger.getLogger(Translator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Translator.class.getName()).log(Level.SEVERE, null, ex);
            }
        
    }

    outAGotoMgoto(node);
}

    @Override
public void caseAToMto(AToMto node){
    inAToMto(node);
    if(node.getTo() != null && node.getIdentifier() != null && node.getLlaveIzq() != null && node.getInstructionlist() != null && node.getLlaveDer() != null)
    {
        Helper.procedimientos.put(node.getIdentifier().getText(),node.getInstructionlist());
        System.out.println("Procedimientos guardados: " + Helper.procedimientos.get(node.getIdentifier().getText()));
    }
    
    outAToMto(node);
}

public void caseAArcMarc(AArcMarc node)
    {
        inAArcMarc(node);
        if(node.getArc() != null && node.getFirst() != null && node.getTcoma() != null && node.getSecond() != null)
        {
            //First es el angulo, second es el radio
                Coordenadas anterior = Helper.getCoordenadas().get(Helper.getTotalCoordenadas()-1);
        	Helper.add(new Coordenadas(anterior.X(), anterior.Y(), Integer.parseInt(node.getFirst().toString().trim()),
                        Helper.getAngleMegaman(),Integer.parseInt(node.getSecond().toString().trim())));
     
        }
        outAArcMarc(node);
    }
public void caseAClearscreenMclr(AClearscreenMclr node)
    {
        inAClearscreenMclr(node);
        if(node.getClearscreen() != null)
        {
                Coordenadas megaPosicion = Helper.getCoordenadas().get(Helper.getTotalCoordenadas()-1);
        	megaPosicion = new Coordenadas(megaPosicion.X(), megaPosicion.Y(), false);
        	Helper.limpiarCoordenadas();
        	Helper.add(megaPosicion);
        	Helper.clearOutput();
        }
        outAClearscreenMclr(node);
    }
public void caseAPenupMpenup(APenupMpenup node)
    {
        inAPenupMpenup(node);
        if(node.getPenup() != null)
        {
           Helper.setPenDown(false);
        }
        outAPenupMpenup(node);
    }
 public void caseAPendownMpendown(APendownMpendown node)
    {
        inAPendownMpendown(node);
        if(node.getPendown() != null)
        {
            Helper.setPenDown(true);
        }
        outAPendownMpendown(node);
    }
 public void caseASetpencolorMspcolor(ASetpencolorMspcolor node)
    {
           inASetpencolorMspcolor(node);
           if(node.getSetpencolor() != null && node.getInteger() != null)
           {
            TInteger integ = node.getInteger();
            int color = Integer.parseInt(integ.getText());
            Helper.setPenColor(color);
            
           }
        outASetpencolorMspcolor(node);
        //NO JALA ESTA MAMADA
    }
 
 public void caseAUniMspsize(AUniMspsize node)
    {
        inAUniMspsize(node);
        if(node.getSetpensize() != null && node.getInteger() != null)
        {
            TInteger integ = node.getInteger();
            int size = Integer.parseInt(integ.getText());
            Helper.setPenSize(size);
            
        }
        outAUniMspsize(node);
        //TAMPOCO JALA ESTA MIERDA
    }
 public void caseAHomeMhome(AHomeMhome node)
    {
        inAHomeMhome(node);
        if(node.getHome() != null)
        {
            Helper.setAngleMegaman(-Helper.getAngleMegaman());
            Helper.add(new Coordenadas(Helper.centerX,Helper.centerY, false));
        }
        outAHomeMhome(node);
    }
   public void caseASetxyMsetxy(ASetxyMsetxy node)
    {
        inASetxyMsetxy(node);
        if(node.getSetxy() != null && node.getFirst() != null &&node.getTcoma() != null && node.getSecond() != null)
        {
            Helper.add(new Coordenadas(Helper.centerX+Integer.parseInt(node.getFirst().getText().trim()),
                            Helper.centerY+Integer.parseInt(node.getSecond().getText().trim()), false));
        }
        outASetxyMsetxy(node);
    }
   public void caseASetxMsetx(ASetxMsetx node)
    {
        inASetxMsetx(node);
        if(node.getSetx() != null && node.getInteger() != null)
        {
        Helper.add(new Coordenadas(Helper.centerX+Integer.parseInt(node.getInteger().getText().trim()),
                                    Helper.getCoordenadas().get(Helper.getCoordenadas().size()-1).Y(),false));
        }
        outASetxMsetx(node);
    }  
    public void caseASetyMsety(ASetyMsety node)
    {
        inASetyMsety(node);
        if(node.getSety() != null && node.getInteger() != null)
        {
          Helper.add(new Coordenadas(Helper.getCoordenadas().get(Helper.getCoordenadas().size()-1).X(),
                  Helper.centerY+Integer.parseInt(node.getInteger().getText().trim()),false));
        }
        outASetyMsety(node);
    }
    
    public void caseASetheadingMsetheading(ASetheadingMsetheading node)
    {
        /*inASetheadingMsetheading(node);
        if(node.getSetheading() != null && node.getInteger() != null)
        {
           if (node.getSetheading())
        		Helper.setTurtleAngle(-Helper.getTurtleAngle()+Integer.parseInt(((ASetheadingPSetheading)
                                                node.getPSetheading()).getInteger().getText().trim()));
        	else
        		Helper.setTurtleAngle(-Helper.getTurtleAngle()+Integer.parseInt(((ASethPSetheading)
                                                node.getPSetheading()).getInteger().getText().trim()));
        }
        
        outASetheadingMsetheading(node); */
    }
    
    public void caseAIfMif(AIfMif node)
    {
        inAIfMif(node);
        if(node.getIf() != null && node.getParentesisIzq() != null && node.getOplogica() != null &&
          node.getParentesisDer() != null && node.getLlaveIzq() != null && 
          node.getInstructionlist() != null && node.getLlaveDer() != null)
        {
            
        }
        outAIfMif(node);
    }
    
}